package testCase;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.Vector;

import org.junit.Test;

//import test.TestActCard_execute.GamePlayerStub;
import junit.framework.TestCase;
import Card.*;
import GameElement.*;
import PlayerElement.*;
import Game.*;

public class TestEventExecution extends TestCase{
	public class GameCardStub extends GameCard{
		public GameCardStub(String [] card_info) {
			card_name = card_info[0];
			card_description = card_info[1];
		}
	};
	
	public class ActCardStub extends GameCardStub{
		private int[][] card_score = new int[6][4];
		public ActCardStub(String[] card_info) {
			super(new String[] {card_info[0],card_info[1]});
			card_score[0][0] = new Integer(card_info[2]);
			// TODO Auto-generated constructor stub
		}
		public String getType(){
			return "ACT";
		}
		public int[][] getCardSocre(){
			return card_score;
		}
	};
	
	public class SayCardStub extends GameCardStub{
		private int[][] card_score = new int[6][4];
		public SayCardStub(String[] card_info) {
			super(new String[] {card_info[0],card_info[1]});
			card_score[0][0] = new Integer(card_info[2]);
			// TODO Auto-generated constructor stub
		}
		public String getType(){
			return "SAY";
		}
		public int[][] getCardSocre(){
			return card_score;
		}
	};
	
	public class EventCardStub extends GameCardStub{
		private int[][] card_score = new int[6][4];
		private String[][] card_answer = new String[6][4];
		public EventCardStub(String[] card_info) {
			super(new String[] {card_info[0],card_info[1]});
			int count = 2;
			for(int i=0; i<6; i++){
				for(int j=0; j<4; j++){
					card_answer[i][j] = new String(card_info[count++]);
					card_score[i][j] = new Integer(card_info[count++]);
				}
			}
		}
		public String getType(){
			return "EVENT";
		}
		public int[][] getCardSocre(){
			return card_score;
		}
		public String[][] getCardAnswer(){
			return card_answer;
		}
	};
	
	public class GamePlayerStub extends GamePlayer{
		public GamePlayerStub(String player_name, String roles){
			super(player_name, roles);
		}
	};
	
	public class GameIOStub extends GameIO{
		GameIOStub(Scanner scn){
			super(scn);
		}
	};
	
	@Test
	public void testPlayer_Position0(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(0);
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 100 + 300;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testPlayer_Position10(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(10);
		
		String data = "A";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 100 + 100;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testPlayer_Position20(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(20);
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 100 - 100;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testPlayer_Position23(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(23);
		
		String data = "A";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 100 + 100;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testPlayer_Position30(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "A";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 100 + 100;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testActCard_Accept_InteractionScore(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(10);
		
		String data = "A";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 60;
		assertEquals(excepted, player[0].getInteractionScore());
	}
	
	@Test
	public void testActCard_Accept_Score(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(10);
		
		String data = "A";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 200;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testActCard_Reject_InteractionScore(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(0);
		
		player[0].modifyPosition(10);
		
		String data = "R";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 40;
		assertEquals(excepted, player[0].getInteractionScore());
	}
	
	@Test
	public void testActCard_Reject_Score(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(10);
		
		String data = "R";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 0;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testActCard_InvalidInput(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new ActCardStub(new String[] {"Dance", "Dance with a family member", "100"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(10);
		
		String data = "B\nA";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 200;  // the score should not be changed
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testSayCard_Accept_CommunicationScore(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new SayCardStub(new String[] {"Love", "Say I love you to one family member", "50"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "A\nN\nN";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 60;
		assertEquals(excepted, player[0].getCommunicationScore());
	}
	
	@Test
	public void testSayCard_Accept_Score(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new SayCardStub(new String[] {"Love", "Say I love you to one family member", "50"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "A\nN\nN";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 150;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testSayCard_Reject_CommunicationScore(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new SayCardStub(new String[] {"Love", "Say I love you to one family member", "50"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "R\nN\nN";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 40;
		assertEquals(excepted, player[0].getCommunicationScore());
	}
	
	@Test
	public void testSayCard_Reject_Score(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new SayCardStub(new String[] {"Love", "Say I love you to one family member", "50"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "R\nN\nN";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 50;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testSayCard_Reject_PlayerA_Feedback_Score(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new SayCardStub(new String[] {"Love", "Say I love you to one family member", "50"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		player[1].setInitScore(100);
		player[2].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "A\nY\nN";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 125;
		assertEquals(excepted, player[1].getScore());
	}
	
	@Test
	public void testSayCard_Reject_PlayerB_Feedback_Score(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new SayCardStub(new String[] {"Love", "Say I love you to one family member", "50"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		player[1].setInitScore(100);
		player[2].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "A\nN\nY";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 125;
		assertEquals(excepted, player[2].getScore());
	}
	
	@Test
	public void testSayCard_Reject_InvalidInput(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		card = new SayCardStub(new String[] {"Love", "Say I love you to one family member", "50"});
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		player[1].setInitScore(100);
		player[2].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "B\nA\nN\nN";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 150;  // the score should not be changed
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testEventCard_CorrectAnswer_UnderstandingScore(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		String[] card_info = {"Case", "A family member did somthing wrong, what would you do? (Base_on_your_role)",
								"Just listen to him/her", "100", "Comfort him/her", "150", "Tell to someone", "50",
								"Do nothing", "-50", "Ask someone for help", "150", "Just listen to him/her", "100",
								"Laugh at him/her", "-100", "Do nothing", "-50", "Ask someone for help", "150",
								"Just listen to him/her", "100", "Laugh at him/her", "-100", "Do nothing", "-50",
								"Ask someone for help",	"150", "Just listen to him/her", "100", "Laugh at him/her", "-100",
								"Do nothing", "-50", "Ask someone for help", "150", "Just listen to him/her", "100",
								"Laugh at him/her", "-100", "Do nothing", "-50", "Ask someone for help", "150",
								"Just listen to him/her", "100", "Laugh at him/her", "-100", "Do nothing", "-50"};
		card = new EventCardStub(card_info);
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "1";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 60;
		assertEquals(excepted, player[0].getUnderstandingScore());
	}
	
	@Test
	public void testEventCard_CorrectAnswer_Score(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		String[] card_info = {"Case", "A family member did somthing wrong, what would you do? (Base_on_your_role)",
								"Just listen to him/her", "100", "Comfort him/her", "150", "Tell to someone", "50",
								"Do nothing", "-50", "Ask someone for help", "150", "Just listen to him/her", "100",
								"Laugh at him/her", "-100", "Do nothing", "-50", "Ask someone for help", "150",
								"Just listen to him/her", "100", "Laugh at him/her", "-100", "Do nothing", "-50",
								"Ask someone for help",	"150", "Just listen to him/her", "100", "Laugh at him/her", "-100",
								"Do nothing", "-50", "Ask someone for help", "150", "Just listen to him/her", "100",
								"Laugh at him/her", "-100", "Do nothing", "-50", "Ask someone for help", "150",
								"Just listen to him/her", "100", "Laugh at him/her", "-100", "Do nothing", "-50"};
		card = new EventCardStub(card_info);
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "1";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 200;
		assertEquals(excepted, player[0].getScore());
	}
	
	@Test
	public void testEventCard_BadAnswer_Score(){
		Vector card_deck = new Vector();
		GameCardStub card = null;
		String[] card_info = {"Case", "A family member did somthing wrong, what would you do? (Base_on_your_role)",
								"Just listen to him/her", "100", "Comfort him/her", "150", "Tell to someone", "50",
								"Do nothing", "-50", "Ask someone for help", "150", "Just listen to him/her", "100",
								"Laugh at him/her", "-100", "Do nothing", "-50", "Ask someone for help", "150",
								"Just listen to him/her", "100", "Laugh at him/her", "-100", "Do nothing", "-50",
								"Ask someone for help",	"150", "Just listen to him/her", "100", "Laugh at him/her", "-100",
								"Do nothing", "-50", "Ask someone for help", "150", "Just listen to him/her", "100",
								"Laugh at him/her", "-100", "Do nothing", "-50", "Ask someone for help", "150",
								"Just listen to him/her", "100", "Laugh at him/her", "-100", "Do nothing", "-50"};
		card = new EventCardStub(card_info);
		card_deck.add(card);
		
		GamePlayerStub[] player = new GamePlayerStub[3];
		player[0] = new GamePlayerStub("Carter", "SON");
		player[1] = new GamePlayerStub("Tracy", "MATHER");
		player[2] = new GamePlayerStub("Peter", "FATHER");
		
		player[0].setInitScore(100);
		
		player[0].modifyPosition(30);
		
		String data = "4";
		System.setIn(new ByteArrayInputStream(data.getBytes()));
		
		EventExecution eventExe = new EventExecution(player[0],player,card_deck, new GameIOStub(new Scanner(System.in)));
		
		int excepted = 50;
		assertEquals(excepted, player[0].getScore());
	}
}
